package com.bitbakery.plugin.cl.lang.psi;

import com.bitbakery.plugin.cl.CLIcons;
import com.bitbakery.plugin.cl.lang.CLElementVisitor;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;

public class CLFunctionCall extends CLElement {
    public CLFunctionCall(ASTNode node) {
        super(node);
    }


    public PsiReference getReference() {
        // Quick hack... Just want to see if this works at all...
        PsiElement match = walk(getContainingFile());
        if (match != null) {
            return new PsiReference() {
                public PsiElement getElement() {
                    return null;  //To change body of implemented methods use File | Settings | File Templates.
                }
                public TextRange getRangeInElement() {
                    return null;  //To change body of implemented methods use File | Settings | File Templates.
                }
                @Nullable
                public PsiElement resolve() {
                    return null;  //To change body of implemented methods use File | Settings | File Templates.
                }
                public String getCanonicalText() {
                    return null;  //To change body of implemented methods use File | Settings | File Templates.
                }
                public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
                    return null;  //To change body of implemented methods use File | Settings | File Templates.
                }
                public PsiElement bindToElement(PsiElement element) throws IncorrectOperationException {
                    return null;  //To change body of implemented methods use File | Settings | File Templates.
                }
                public boolean isReferenceTo(PsiElement element) {
                    return false;  //To change body of implemented methods use File | Settings | File Templates.
                }
                public Object[] getVariants() {
                    return new String[]{"Heeba", "Feeba"};
                }
                public boolean isSoft() {
                    return false;
                }
            };
        }
        return super.getReference();
    }

    private PsiElement walk(PsiElement element) {
        return null;
    }

    public CLArgumentList getArgumentList() {
        return (CLArgumentList) getNode().findChildByType(CLElementTypes.ARGUMENT_LIST).getPsi();
    }

    public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
/*
        TODO - Implementing this guy is needed for rename refactorings

        final ASTNode nameElement = JSChangeUtil.createNameIdentifier(getProject(), name);
        getNode().replaceChild(findName(), nameElement);
*/
        return this;
    }

    public boolean processDeclarations(PsiScopeProcessor processor,
                                       PsiSubstitutor substitutor,
                                       PsiElement lastParent,
                                       PsiElement place) {
        if (lastParent != null && lastParent.getParent() == this) {
            for (CLArgument arg : getArgumentList().getArguments()) {
                if (!processor.execute(arg, substitutor)) {
                    return false;
                }
            }
        }

        return processor.execute(this, substitutor);
    }

    public void accept(@NotNull PsiElementVisitor visitor) {
        if (visitor instanceof CLElementVisitor) {
            ((CLElementVisitor) visitor).visitCommonLispFunctionCall(this);
        } else {
            visitor.visitElement(this);
        }
    }

    public String toString() {
        return "CLFunctionCall";
    }

    public Icon getIcon(int flags) {
        return CLIcons.COMMON_LISP_DEFUN_NODE;
    }
}
